0. 前言
实际上Spring Boot已经默认搭建了Spring和Spring MVC框架的配置(通过一个名为spring-boot-starter-web
的maven依赖),使用起来只需简单的在代码上写好注解就好了(一般使用注解的形式),无需配置,具体说明在代码中(配有注释)。SSM三大框架两个都配置好了,就还剩下Mybatis的配置,这个需要手动设置,也很简单,以下说明。
建议:
初次尝试推荐直接使用之前SPRING INITIALIZR生成的项目,在此基础上进行修改即可。
1. Spring Boot整合Mybatis集成Mysql数据库
这里使用Druid的数据源连接池来整合Mybatis。
使用Druid数据源的配置方式比较麻烦,因为除了配置连接池的参数外,还要配置filter监控拦截sql。如果使用别的数据源比如DBCP、c3p0等,就可以省去很多麻烦,不需要在java类中进行手动配置,直接在配置文件说明参数即可。但Druid配置监控的好处是可以实时监控项目中数据源的使用情况,比如监控执行sql的耗时与使用次数等…
1.1 项目结构
重申一遍,入口类最好放置在与dao、service、controller同级的目录下
1.2 pom.xml文件
1 | <?xml version="1.0" encoding="UTF-8"?> |
1.3 application.yml文件
1 | spring: |
1.4 logback.xml文件
这里使用logback日志文件进行记录。
名词解释——logback
log4j是apache实现的一个开源日志组件。logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架。是slf4j的原生实现。
logback.xml文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="10 seconds">
<include resource="org/springframework/boot/logging/logback/base.xml" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_PATH}/info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/info-%d{yyyyMMdd}.log.%i</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
</Pattern>
</layout>
</appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${LOG_PATH}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
</Pattern>
</layout>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
<!-- <appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" /> -->
</root>
</configuration>
1.5 DatasourceConfig.java
DatasourceConfig.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143package com.boot.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
@Configuration // 使用该注解表明这是一个配置类,相当于传统的xml配置文件
public class DruidDataSourceConfig{
private Logger logger = LoggerFactory.getLogger(DruidDataSourceConfig.class);
// @Value用于读取配置文件中的键值对
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.type}")
private String dbType;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.filters}")
private String filters;
@Value("${spring.datasource.connectionProperties}")
private String connectionProperties;
@Value("${spring.datasource.useGlobalDataSourceStat}")
private boolean useGlobalDataSourceStat;
@Value("${spring.datasource.druidLoginName}")
private String druidLoginName;
@Value("${spring.datasource.druidPassword}")
private String druidPassword;
@Bean(name="dataSource",destroyMethod = "close", initMethod="init")
@Primary //有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。
public DataSource dataSource(){
DruidDataSource datasource = new DruidDataSource();
try {
datasource.setUrl(this.dbUrl);
datasource.setDbType(dbType);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setFilters(filters);
datasource.setConnectionProperties(connectionProperties);
datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
return datasource;
}
///////// 下面是druid 监控访问的设置 /////////////////
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*"); //url 匹配
reg.addInitParameter("allow", "192.168.16.110,127.0.0.1"); // IP白名单 (没有配置或者为空,则允许所有访问)
reg.addInitParameter("deny", "192.168.16.111"); //IP黑名单 (存在共同时,deny优先于allow)
reg.addInitParameter("loginUsername", this.druidLoginName);//登录名
reg.addInitParameter("loginPassword", this.druidPassword);//登录密码
reg.addInitParameter("resetEnable", "false"); // 禁用HTML页面上的“Reset All”功能
return reg;
}
@Bean(name="druidWebStatFilter")
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); //忽略资源
filterRegistrationBean.addInitParameter("profileEnable", "true");
filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION");
return filterRegistrationBean;
}
}
1.6 MybatisConfig.java
1 | package com.boot.config; |
1.7 Model类
UserInfo.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35package com.boot.pojo.po;
import java.io.Serializable;
import java.sql.Date;
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String userId;
private String nickName;
private String sex;
private Date birthDate;
private String province;
private String city;
private String introduction;
public UserInfo() {
super();
}
public UserInfo(String userId, String nickName, String introduction, String sex, Date birthDate,
String province, String city) {
super();
this.userId = userId;
this.nickName = nickName;
this.introduction = introduction;
this.sex = sex;
this.birthDate = birthDate;
this.province = province;
this.city = city;
}
// 省略getter和setter方法
}
1.8 mapper文件
UserInfoMapper.xml1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.boot.dao.UserInfoDao">
<insert id="save">
INSERT INTO
t_user_info(user_id, nick_name)
VALUES
(#{userId}, #{nickName})
</insert>
<select id="getByUserId" parameterType="String" resultMap="userInfo">
SELECT * FROM
t_user_info
WHERE
user_id = #{userId}
</select>
<update id="updateByUserId" parameterType="com.boot.pojo.po.UserInfo">
UPDATE
t_user_info
<set>
<if test="nickName != null">
nick_name = #{nickName},
</if>
<if test="introduction != null">
introduction = #{introduction},
</if>
<if test="sex != null">
sex = #{sex},
</if>
<if test="birthDate != null">
birth_date = #{birthDate},
</if>
<if test="province != null">
province = #{province},
</if>
<if test="city != null">
city = #{city},
</if>
</set>
WHERE
user_id = #{userId}
</update>
<select id="listAll" resultMap="userInfo" >
SELECT * FROM
t_user_info
</select>
<resultMap type="com.boot.pojo.po.UserInfo" id="userInfo">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="nickName" column="nick_name"/>
<result property="introduction" column="introduction"/>
<result property="sex" column="sex"/>
<result property="birthDate" column="birth_date"/>
<result property="province" column="province"/>
<result property="city" column="city"/>
</resultMap>
</mapper>
1.9 Dao类
UserInfoDao1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.boot.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.cache.annotation.Cacheable;
import com.boot.pojo.po.UserInfo;
@Mapper // 表明这是mapper对应的java接口
public interface UserInfoDao {
void updateByUserId(UserInfo userInfo);
UserInfo getByUserId(@Param("userId") String userId);
List<UserInfo> listAll();
}
1.10 Service类(省略)
和以往使用Spring框架相同,省略
1.11 Controller类
UserInfoController1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package com.boot.controller;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.boot.other.enums.StateCodeEnum;
import com.boot.pojo.dto.PageUserInfo;
import com.boot.service.UserInfoService;
import com.github.pagehelper.PageInfo;
@RestController // 表明使用Restful的API,函数的返回值直接填入HTTP响应体中,返回Map就当成返回Json格式数据
@EnableAutoConfiguration // 使用自动配置 (这里可能多余了)
@RequestMapping("/boot")
public class UserInfoController {
private UserInfoService userInfoService;
@RequestMapping(value = "/user/info/get", method = RequestMethod.POST)
public Map<String, Object> get(@RequestBody Map<String, String> map) {
// 省略逻辑代码
}
@Resource(name = "userInfoService") // 和以前一样,也可以用@Autowired
public void setUserInfoService(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
}
1.12 Application启动类
MyApplication.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package com.boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
// 该注解包含了三个注解
// 1. @MapperScan: 指定扫描Component所在的包并进行注入,
// 如果不使用该注解,默认会扫描启动类所在包下以及子包下的使用了@Service,@Repository等注解的类。
// 2. @EnableAutoConfiguration Spring Boot自动配置(auto-configuration):尝试根据你添加的jar依赖自动配置你的Spring应用。
// 3. @Configuration
// 以上三个注解往往会一起使用,于是官方合并成了一个@SpringBootApplication
@SpringBootApplication(scanBasePackages = {"com.boot"})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
1.13 结果检验
之后,启动项目,访问http://127.0.0.1:8080/boot/user/info/get, 不出意外就能获得json格式的响应。以下是使用Postman的测试结果:
查看Druid的监控画面,在浏览器输入http://127.0.0.1:8080/druid,会弹出一个登录界面,要求你输入在application.yml文件中设置的Druid的登录账号和密码
登录成功,就可以查看监控
2. Spring Boot集成Mongo数据库
如果成功的整合了Mybatis,那么集成MongoDB就简单得多了,很多事情Spring Boot都替我们做好了
2.1 pom.xml
pom.xml文件加入1
2
3
4
5<!-- Spring boot集成Mongodb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2.2 application.yml文件
application.yml文件加入1
2
3
4
5# Mongodb的配置
spring:
data:
mongodb:
uri: mongodb://账号:密码@localhost:27017/test
注意,若同时配置MongoDB与Mybatis,二者前缀都含有spring,则父结点必须并在一起写。
2.3 Dao类
UserDao类1
2
3
4
5
6
7
8
9
10package com.boot.dao;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.boot.pojo.po.User;
// 直接继承MongoRepository,Spring会有默认的实现
// 如果想自己写实现类,直接注入MongoTemplate即可,Spring Boot会有自动配置(启动类使用@EnableAutoConfiguration)
public interface UserDao extends MongoRepository<User, String>{
}
注意,这里的类并没有任何的注解,如果使用自定义的实现请在实现类上使用注解@Repository
2.4 Controller类
省略Service类
UserController类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.boot.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.boot.dao.UserDao;
import com.boot.pojo.po.User;
@RestController
@RequestMapping("/boot")
public class UserController {
@Autowired
private UserDao userDao;
@RequestMapping(value = "/user/list", method = RequestMethod.POST)
public Map<String, Object> list() {
// 略
}
}
2.5 结果检验
使用Postman进行检验
如果只是搭单一Mongo数据源,不使用集群,就是这么简单就完成了。
3. Spring Boot集成Redis数据库
3.1 pom.xml文件
pom.xml文件1
2
3
4
5<!-- Spring boot集成Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.2 application.yml文件
application.yml文件加入1
2
3
4
5
6
7
8
9
10spring:
redis:
host: 127.0.0.1
port: 6379
timeout: 20000
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
3.3 Dao类
UserTokenDao类1
2
3
4
5
6
7
8
9
10
11
12package com.boot.dao;
import com.boot.pojo.po.UserToken;
public interface UserTokenDao {
void save(UserToken userToken);
UserToken getByUserId(String userId);
void removeByUserId(String userId);
}
UserTokenDaoImpl1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39package com.boot.dao.impl;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import com.boot.dao.UserTokenDao;
import com.boot.pojo.po.UserToken;
@Repository
public class UserTokenDaoImpl implements UserTokenDao{
@Autowired
private StringRedisTemplate redisTemplate;
private final static int TTL = 31; // 过期时间:31天。即31天后自动删除
@Override
public void save(UserToken userToken) {
redisTemplate.boundValueOps(userToken.getUserId()).set(userToken.getToken(), TTL, TimeUnit.DAYS);
}
@Override
public UserToken getByUserId(String userId) {
String token = (String)redisTemplate.opsForValue().get(userId);
UserToken userToken = new UserToken();
userToken.setUserId(userId);
userToken.setToken(token);
return userToken;
}
@Override
public void removeByUserId(String userId) {
redisTemplate.delete(userId);
}
}
3.4 Controller类
和Mongo的Controller一样,这里就不写了。
3.5 结果检验(略)
4. 总结
至此,Spring Boot的简单使用,搭建一个简单的SSM框架已经完成,同时集成了MongoDB、Redis数据库。
另外,关于Spring Boot,官方不推荐使用jsp动态页面,要完整的配置返回jsp视图会比较麻烦,最好也不要这么做,如果要使用动态页面,可参考Thymeleaf组件。
Copyright © 2018, CSCW back-end Kanarien, All Rights Reserved